﻿using System;
using System.Collections.Generic;
using System.Text;
using AviFile;
using System.IO;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.Xml;
using System.Linq;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Configuration;
using System.Reflection;
using System.Diagnostics;
using System.Threading;
using System.Xml.Serialization;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure;
using System.Drawing.Drawing2D;

namespace CloudVideoRenderer
{
    public class CloudVideoRenderer : ICloudVideoRenderer
    {
        private static Image resizeImage(Image imgToResize, Size size)
        {
            int sourceWidth = imgToResize.Width;
            int sourceHeight = imgToResize.Height;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)size.Width / (float)sourceWidth);
            nPercentH = ((float)size.Height / (float)sourceHeight);

            if (nPercentH < nPercentW)
                nPercent = nPercentH;
            else
                nPercent = nPercentW;

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap b = new Bitmap(destWidth, destHeight);
            Graphics g = Graphics.FromImage((Image)b);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
            g.Dispose();

            return (Image)b;
        }

        public void RenderVideo(string cameraId, string storePath, int frameRate)
        {
            string executableDirectoryPath = storePath;

            StoreImagesFromDB(cameraId, executableDirectoryPath);


            if (!Directory.Exists(executableDirectoryPath)) return;

            string[] files = Directory.GetFiles(executableDirectoryPath, cameraId + "*.jpg");

            foreach (string f in files)
            {
                using (Image img = Image.FromFile(f))
                {
                    resizeImage(img, new Size(640, 480)).Save(f.Substring(0, f.Length - 4) + ".bmp", ImageFormat.Bmp);
                }
            }


            //Bitmap bitmap = (Bitmap)Image.FromFile(files[0].Substring(0, files[0].Length - 4) + ".bmp");
            ////create a new AVI file
            //AviManager aviManager =
            //    new AviManager(cameraId + ".avi", false);
            ////add a new video stream and one frame to the new file
            //VideoStream aviStream =
            //    aviManager.AddVideoStream(true, 2, bitmap);

            string pathToExecutable = Path.Combine(executableDirectoryPath, "bmp2avi.exe");

            //ProcessStartInfo psi = new ProcessStartInfo();
            //psi.FileName = pathToExecutable;
            //psi.Arguments = @"-i " + Path.Combine(path, cameraId) + " -f " + frameRate.ToString() + " -o " + Path.Combine(path, cameraId) + ".avi";
            //psi.CreateNoWindow = true;
            //psi.ErrorDialog = true;
            //psi.UseShellExecute = true;
            //psi.WindowStyle = ProcessWindowStyle.Normal;
            //psi.RedirectStandardOutput = false;
            //psi.RedirectStandardError = false;

            //string outString = string.Empty;
            //string errString = string.Empty;

            //Trace.WriteLine("Going to execute bmp2avi.exe", "Notifications");
            //// Start the process with the info we specified.
            //// Call WaitForExit and then the using statement will close.
            //using (Process exeProcess = Process.Start(psi))
            //{
            //    StreamReader output = exeProcess.StandardOutput;
            //    StreamReader error = exeProcess.StandardError;
            //    //exeProcess.WaitForExit();
            //    outString = output.ReadToEnd();
            //    errString = error.ReadToEnd();
            //}


            File.WriteAllText(Path.Combine(storePath, "runme.bat"), "bmp2avi.exe " + " -i " + cameraId + " -f " + frameRate.ToString() + " -o " + cameraId);
            Process p = new Process()
            {
                StartInfo = new ProcessStartInfo(pathToExecutable, "-i " + cameraId + " -f " + frameRate.ToString() + " -o " + cameraId)
                {
                    UseShellExecute = false,
                    WorkingDirectory = executableDirectoryPath
                }
            };

            p.Start();
            p.WaitForExit();

            CloudBlobClient blobClient = new CloudBlobClient("http://[storage account name].blob.core.windows.net/", new StorageCredentialsAccountAndKey("[storage account name]", "[storage access key]"));

            //Get a reference to a container, which may or may not exist.
            CloudBlobContainer container = blobClient.GetContainerReference("cloudvideo");

            //Create a new container, if it does not exist
            container.CreateIfNotExist();

            string aviFile = Path.Combine(Path.GetDirectoryName(pathToExecutable), cameraId + ".avi");

            //Get a reference to a blob, which may or may not exist.
            CloudBlob blob = container.GetBlobReference(Path.GetFileName(aviFile).ToLower());

            //Move the calculation output from local storage to blob storage.
            try
            {
                blob.UploadFile(aviFile);
            }
            catch (Exception ex)
            {

                Trace.WriteLine("Error uploading blob. Message:" + ex.Message + ": " + ex.InnerException.Message, "Errors");
                throw ex;
            }


            //Bitmap bitmapadd;
            //int count = 0;
            //for (int n = 1; n < files.Length; n++)
            //{
            //    if (files[n].Trim().Length > 0)
            //    {
            //        bitmapadd =
            //           (Bitmap)Bitmap.FromFile(files[n].Substring(0, files[n].Length - 4) +
            //           ".bmp");
            //        aviStream.AddFrame(bitmapadd);
            //        bitmapadd.Dispose();
            //        count++;
            //    }
            //}
            //aviManager.Close();
        }

        private void StoreImagesFromDB(string cameraId, string storePath)
        {
            var context = new CloudObserverDB.CloudObservationContext();

            var query = context.CloudObservations
                      .Where(o => o.CameraId == cameraId)
                      .OrderBy(o => o.ObservationTimeStamp)
                      .ToList();

            int indexer = 0;
            foreach (var observation in query)
            {
                MemoryStream ms = new MemoryStream(observation.Image);
                Image returnImage = Image.FromStream(ms);

                try
                {
                    returnImage.Save(Path.Combine(storePath, cameraId.Trim() + indexer.ToString("D9")) + ".jpg");
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("Error saving image. Message:" + ex.Message + ": " + ex.InnerException.Message, "Errors");
                    throw ex;
                }
                indexer++;
            }
        }
    }
}
